package com.jinsp.skinlib;

import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by luoshuai on 10/27/21
 * <p>
 * 负责创建xml中的view标签
 */
public class ActivityViewManager implements LayoutInflater.Factory2 {

    private static final String VIEW_RESOURCE_NAME_BACKGROUND = "background";           // view背景色标签名
    private static final String VIEW_RESOURCE_NAME_SRC = "src";                         // ImageView背景图片标签名
    private static final String VIEW_RESOURCE_NAME_TEXT_COLOR = "textColor";            // textView中文字的颜色标签名
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_START = "drawableStart";    // View中drawableStart
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_LEFT = "drawableLeft";      // View中drawableLeft
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_END = "drawableEnd";        // View中drawableEnd
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_RIGHT = "drawableRight";    // View中drawableRight
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_TOP = "drawableTop";        // View中drawableTop
    private static final String VIEW_RESOURCE_NAME_DRAWABLE_BOTTOM = "drawableBottom";  // View中drawableBottom
    private static final String VIEW_RESOURCE_NAME_TEXT = "text";                       //TextView中text文本
    //view所在包的前缀，例如使用的TextView完整包就是android.widget.TextView
    private final static String[] mClassPrefixList = {
            "android.widget.",
            "android.webkit.",
            "android.app.",
            "android.view."
    };

    //包含所有可换肤的view
    private List<SkinView> mSkinViewList = new ArrayList<>();
    //是否已经更换了资源
    protected boolean isResourcesAlreadyUpdate = true;

    //定义需要更换资源的属性列表
    private static final List<String> VIEW_ATTRIBUTE_NAME_LIST = new ArrayList<>();

    static {
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_BACKGROUND);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_TEXT_COLOR);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_SRC);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_TEXT);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_START);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_LEFT);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_RIGHT);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_END);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_TOP);
        VIEW_ATTRIBUTE_NAME_LIST.add(VIEW_RESOURCE_NAME_DRAWABLE_BOTTOM);
    }

    //创建view构造器
    private static final Class<?>[] mConstructorSignature = new Class[]{
            Context.class, AttributeSet.class};

    private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
            new HashMap<>();

    @Nullable
    @Override
    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
        View view = createView(context, attrs, name);
        if (view != null) {
            //获取view标签中的属性标签
            findViewAttribute(view, attrs);
        }
        return view;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
        return null;
    }

    /**
     * 创建view
     *
     * @param context 上下文
     * @param attrs   view对应的属性
     * @param name    view的名称
     * @return 该view
     */
    private View createView(Context context, AttributeSet attrs, String name) {
        if (!name.contains(".")) {
            //需要我们填充完整包名
            for (String packageName : mClassPrefixList) {
                View view = createView(context, attrs, packageName + name);
                if (view != null) {
                    return view;
                }
            }
        }
        Constructor<? extends View> constructor = findConstructor(context, name);
        if (constructor == null) {
            return null;
        }
        try {
            //反射创建view对象
            return constructor.newInstance(context, attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据view名找到对应的构造器
     *
     * @param context 上下文
     * @param name    view名
     * @return 该view对应的构造器
     */
    private Constructor<? extends View> findConstructor(Context context, String name) {
        Constructor<? extends View> constructor = sConstructorMap.get(name);
        if (constructor == null) {
            try {
                Class<? extends View> clazz = context.getClassLoader().loadClass(name)
                        .asSubclass(View.class);
                constructor = clazz.getConstructor(mConstructorSignature);
                constructor.setAccessible(true);
                sConstructorMap.put(name, constructor);
            } catch (Exception e) {
                return null;
            }
        }
        return constructor;
    }

    /**
     * 遍历view中的xml标签属性，获取需要换肤的属性view
     *
     * @param view  当前正在遍历的view节点
     * @param attrs view对应的属性
     */
    private void findViewAttribute(View view, AttributeSet attrs) {
        List<SkinViewAttribute> mSkinViewAttributeList = null;
        int attrCount = attrs.getAttributeCount();
        for (int i = 0; i < attrCount; i++) {
            String attributeName = attrs.getAttributeName(i);
            if (VIEW_ATTRIBUTE_NAME_LIST.contains(attributeName)) {
                if (mSkinViewAttributeList == null) {
                    mSkinViewAttributeList = new ArrayList<>();
                }
                //该view包含可以换肤的属性
                String attrValue = attrs.getAttributeValue(i);
                if (attrValue.startsWith("#")) {
                    //xml内部固定数值，不可改动
                    continue;
                }
                int resId = 0;
                if (attrValue.startsWith("?")) {
                    int attrId = Integer.parseInt(attrValue.substring(1));
                    //使用系统系统资源
                    resId = ResourceManager.getInstance().getThemeResId(view.getContext(), attrId)[0];
                } else if (attrValue.startsWith("@")) {
                    //使用自己写的资源引用
                    resId = Integer.parseInt(attrValue.substring(1));
                }
                //id为0表示找不到资源
                if (resId != 0) {
                    SkinViewAttribute skinViewAttribute = new SkinViewAttribute(attributeName, resId);
                    mSkinViewAttributeList.add(skinViewAttribute);
                }
            }
        }
        if (view instanceof CustomViewSupport || (mSkinViewAttributeList != null
                && mSkinViewAttributeList.size() > 0)) {
            SkinView skinView = new SkinView(view, mSkinViewAttributeList);
            skinView.applyResource();
            mSkinViewList.add(skinView);
        }
    }

    /**
     * 外部调用手动更换APP皮肤
     *
     * @param skinFilePath 插件APK路径
     */
    public void changeSkinResource(String skinFilePath) {
        ResourceManager.getInstance().loadSkinResource(skinFilePath);
        startChange();
        //修改未更新页面状态为等待更新资源
        for (Map.Entry<Activity, ActivityViewManager> entry : SkinActivityLifecycleCallback.activityViewManagerMap.entrySet()) {
            ActivityViewManager activityViewManager = entry.getValue();
            activityViewManager.isResourcesAlreadyUpdate = false;
        }
    }

    public void startChange() {
        isResourcesAlreadyUpdate = true;
        //更换当前页面资源
        for (SkinView skinView : mSkinViewList) {
            skinView.applyResource();
        }
    }

    /**
     * 清除view
     */
    public void release() {
        if (mSkinViewList.size() > 0) {
            mSkinViewList.clear();
            mSkinViewList = null;
        }
    }

    //需要更换皮肤资源的View
    private static class SkinView {

        private final View view;          //创建的view对象
        private final List<SkinViewAttribute> mSkinViewAttributeList; //该对象对应需要换肤的xml键值对

        private SkinView(View view, List<SkinViewAttribute> mSkinViewAttributeList) {
            this.view = view;
            this.mSkinViewAttributeList = mSkinViewAttributeList;
        }

        private void applyResource() {
            //应用资源
            changeResourceForCustomView();
            if (mSkinViewAttributeList != null && mSkinViewAttributeList.size() > 0) {
                for (SkinViewAttribute skinViewAttribute : mSkinViewAttributeList) {
                    int resId = skinViewAttribute.resId;
                    switch (skinViewAttribute.attributeName) {
                        case VIEW_RESOURCE_NAME_BACKGROUND: {
                            //加载背景色资源
                            Object background = ResourceManager.getInstance().getBackground(resId);
                            if (background instanceof Integer) {
                                view.setBackgroundColor((int) background);
                            } else if (background instanceof Drawable) {
                                view.setBackground((Drawable) background);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_SRC: {
                            //ImageView功能
                            if (view instanceof ImageView) {
                                ImageView imageView = (ImageView) view;
                                Object src = ResourceManager.getInstance().getBackground(resId);
                                if (src instanceof Integer) {
                                    imageView.setImageDrawable(new ColorDrawable((int) src));
                                } else if (src instanceof Drawable) {
                                    imageView.setImageDrawable((Drawable) src);
                                }
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_TEXT_COLOR: {
                            //更换文字颜色，TextView功能
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setTextColor(ResourceManager.getInstance().getColor(resId));
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_TEXT: {
                            //更换文字，TextView功能
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setText(ResourceManager.getInstance().getStringId(resId));
                                //设置文字字体
                                /*Typeface typeface = ResourceManager.getInstance().getSkinTypeface();
                                if (typeface == null) {
                                    textView.setTypeface(Typeface.DEFAULT);
                                } else {
                                    textView.setTypeface(typeface);
                                }*/
                            }
                        }
                        break;
                        /*case VIEW_RESOURCE_NAME_TYPE_FACE: {
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                //8.0以上更换字体
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                                    textView.setTypeface(ResourceManager.getInstance().getFont(resId));
                                } else {
                                    //8.0一下沿用设定字体
                                    textView.setTypeface(ResourcesCompat.getFont(view.getContext(), resId));
                                }
                            }
                        }
                        break;*/
                        case VIEW_RESOURCE_NAME_DRAWABLE_LEFT: {
                            //更换TextView中开始图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesWithIntrinsicBounds(ResourceManager.getInstance().getDrawable(resId),
                                        null, null, null);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_DRAWABLE_START: {
                            //更换TextView中开始图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesRelativeWithIntrinsicBounds(ResourceManager.getInstance().getDrawable(resId),
                                        null, null, null);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_DRAWABLE_RIGHT: {
                            //更换TextView中结尾图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesWithIntrinsicBounds(null,
                                        null, ResourceManager.getInstance().getDrawable(resId), null);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_DRAWABLE_END: {
                            //更换TextView中结尾图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesRelativeWithIntrinsicBounds(null,
                                        null, ResourceManager.getInstance().getDrawable(resId), null);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_DRAWABLE_TOP: {
                            //更换TextView中顶部图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesWithIntrinsicBounds(null,
                                        ResourceManager.getInstance().getDrawable(resId), null, null);
                            }
                        }
                        break;
                        case VIEW_RESOURCE_NAME_DRAWABLE_BOTTOM: {
                            //更换TextView中底部图标
                            if (view instanceof TextView) {
                                TextView textView = (TextView) view;
                                textView.setCompoundDrawablesWithIntrinsicBounds(null,
                                        null, null, ResourceManager.getInstance().getDrawable(resId));
                            }
                        }
                        break;
                        default:
                            break;
                    }
                }
            }
        }

        /**
         * 自定义view实现该接口
         */
        private void changeResourceForCustomView() {
            if (view instanceof CustomViewSupport) {
                ((CustomViewSupport) view).changeResource();
            }
        }
    }

    //定义了View标签中需要更换资源的键值对，包括名称以及对应的id
    private static class SkinViewAttribute {

        private final String attributeName;
        private final int resId;

        private SkinViewAttribute(String attributeName, int resId) {
            this.attributeName = attributeName;
            this.resId = resId;
        }
    }
}
